#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
数据库表模型
script name: models
Created on 2020/1/2 14:00 by PyCharm
@author: fujianjian
"""
from flask import current_app
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer

from . import db


class Role(db.Model):
    """
    角色表模型
    """
    __tablename__ = 'roles'
    id = db.Column(db.Integer, primary_key=True, name='pri_id', autoincrement=True)
    name = db.Column(db.String(64), unique=True, name='role_name')
    code = db.Column(db.String(32), nullable=False, unique=True, name='role_code')


class User(UserMixin, db.Model):
    """
    用户表模型
    """
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True, name='pri_id', autoincrement=True)
    email = db.Column(db.String(64), unique=True, name='email', index=True)
    username = db.Column(db.String(64), unique=True, name='username', index=True)
    password_hash = db.Column(db.String(512), nullable=False, unique=True, name='password')
    confirmed = db.Column(db.Boolean, default=False, nullable=False, name='confirmed')

    @property
    def password(self):
        raise AttributeError('password is not readable attribute')

    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)

    def generate_confirmation(self, expired=3600):

        s = Serializer(current_app.config['SECRET_KEY'], expired)
        token = s.dumps({'confirm': self.id}).decode('utf-8')
        print('generated confirm token: ', token)
        return token

    def confirm(self, token):
        """
        确认用户
        :param token:
        :return:
        """
        s = Serializer(current_app.config['SECRET_KEY'])
        try:
            data = s.loads(token.encode('utf-8'))

        except EOFError as e:
            print('confirm token error: ', e)
            return False
        if data.get('confirm') != self.id:
            return False
        self.confirmed = True
        db.session.add(self)
        db.session.commit()
        return True

    @property
    def is_active(self):
        return True

    def __repr__(self) -> str:
        return '<User %r>' % self.username
